use chrono::offset::TimeZone;
use clap::Clap;
use futures::StreamExt;
use std::io::Write;

const SERVER_URL_BASE: &'static str = "tcp://18.163.136.233";

#[derive(Clap)]
#[clap(version = "1.0", author = "Donggu Kang")]
struct Opts {
    #[clap(long)]
    symbol: Symbol,
    #[clap(long)]
    local: bool,
}

#[derive(Copy, Clone, Clap, strum_macros::EnumString)]
enum Symbol {
    Swap,
    Futures,
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let opts: Opts = Opts::parse();
    let url = format!(
        "{}:{}",
        if opts.local {
            "tcp://127.0.0.1"
        } else {
            SERVER_URL_BASE
        },
        match opts.symbol {
            Symbol::Swap => 5124,
            Symbol::Futures => 5125,
        }
    );

    let mut socket = tmq::subscribe(&tmq::Context::new())
        .connect(&url)?
        .subscribe(b"")?;

    println!("{}", url);

    // socket.subscribe(b"book")?;

    let f = std::fs::File::create(match opts.symbol {
        Symbol::Swap => "swap.txt",
        Symbol::Futures => "futures.txt",
    })?;
    let mut f = std::io::LineWriter::new(f);

    while let Some(Ok(msg)) = socket.next().await {
        let mut it = msg.iter();
        let _topic = it.next().unwrap().as_str().unwrap_or("invalid text");
        let rt = it
            .next()
            .unwrap()
            .as_str()
            .unwrap_or("invalid text")
            .parse::<i64>()
            .unwrap();
        let msg = it.next().unwrap().as_str().unwrap_or("invalid text");

        let json: serde_json::Value = serde_json::from_str(&msg[..])?;

        if json["data"][0]["timestamp"].is_null() {
            continue;
        }
        let ft = chrono::Utc::now();
        let rt = chrono::Utc.timestamp(rt / 1_000_000_000, (rt % 1_000_000_000) as u32);
        let et =
            chrono::DateTime::parse_from_rfc3339(json["data"][0]["timestamp"].as_str().unwrap())
                .unwrap();
        // let et: i64 = et.timestamp() * 1_000_000_000i64 + et.timestamp_subsec_nanos() as i64;
        if opts.local {
            println!(
                "et {:?} {} rt {:?} {} ft {:?} {} msg {}",
                et,
                et.timestamp() * 1_000_000_000i64 + et.timestamp_subsec_nanos() as i64,
                rt,
                rt.timestamp() * 1_000_000_000i64 + rt.timestamp_subsec_nanos() as i64,
                ft,
                ft.timestamp() * 1_000_000_000i64 + ft.timestamp_subsec_nanos() as i64,
                msg
            );
        } else {
            writeln!(
                &mut f,
                "et {:?} {} rt {:?} {} ft {:?} {} msg {}",
                et,
                et.timestamp() * 1_000_000_000i64 + et.timestamp_subsec_nanos() as i64,
                rt,
                rt.timestamp() * 1_000_000_000i64 + rt.timestamp_subsec_nanos() as i64,
                ft,
                ft.timestamp() * 1_000_000_000i64 + ft.timestamp_subsec_nanos() as i64,
                msg
            )?;
        }
    }
    Ok(())
}
